package Utilities;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import org.apache.commons.math.linear.OpenMapRealMatrix;
import org.apache.commons.math.linear.SparseRealMatrix;

public class Distancematrix {
	
//	float[][] matrix;
	float[][] datas;
	SparseRealMatrix sparseMatrix;
	boolean liveCalc=true;
	
	public Distancematrix(float[][] datas){

		this.datas=datas;
//		matrix = new float[datas.length][];
		sparseMatrix = new OpenMapRealMatrix(datas.length, datas.length);
		
		if(!liveCalc)
		for (int i = 0; i < datas.length; i++) {
			if(i%50==0)
				System.out.println(i +" of "+ datas.length);
			
//			matrix[i]=new float[i+1];
//			matrix[i][i] = 0;
					
			for (int j = 0; j < i; j++) {

				float d = distance(datas[i], datas[j]);
//				matrix[i][j] = d;	
				sparseMatrix.setEntry(i, j, d);
			}
			}
//		else
//			for (int i = 0; i < datas.length; i++) {
//				matrix[i] = new float[i + 1];
//			}
		
		
//		for (int i = 0; i < datas.length; i++) 
//			System.out.println(Arrays.toString(distanceMatrix[i]));
				
	}
	
	public float getDistance(int one, int two){
//		if (!liveCalc)
//			if (one < two)
//				return matrix[two][one];
//			else
//				return matrix[one][two];
//		else if (one < two) {
//			if (matrix[two][one] == 0)
//				matrix[two][one] = distance(datas[two], datas[one]);
//			return matrix[two][one];
//		} else {
//			if (matrix[one][two] == 0)
//				matrix[one][two] = distance(datas[two], datas[one]);
//			return matrix[one][two];
//		}
		
		if (!liveCalc)
			if (one < two)
				return (float) sparseMatrix.getEntry(two, one);
			else
				return (float) sparseMatrix.getEntry(one, two);
		else if (one < two) {
			if (sparseMatrix.getEntry(two, one) == 0)
				sparseMatrix.setEntry(two, one, distance(datas[two], datas[one]));
			return (float) sparseMatrix.getEntry(two, one);
		} else {
			if (sparseMatrix.getEntry(one, two) == 0)
				sparseMatrix.setEntry(one, two, distance(datas[two], datas[one]));
			return (float) sparseMatrix.getEntry(one, two);
		}
		
	}
	
	
	float distance(float[] one, float[] two){
		float d=0;
		
		// eucledean metric
		for(int i =0; i< one.length;i++)
			d+=Math.pow(one[i]-two[i], 2);
		
		d= (float) Math.sqrt(d);
						
		return d;
	}
	
	public float findPercentageOfNotCalcDistance(){
		
		int nrOfNotCalc=0;
		
		for (int i = 0; i < datas.length; i++) {
			for (int j = 0; j < i; j++) {				
//				if(matrix[i][j] == 0)
				if(sparseMatrix.getEntry(i, j) == 0)
					nrOfNotCalc++;
			}
		}
		
		int nrOfAll =(int)(Math.pow(datas.length, 2)/2-datas.length);
		
		return nrOfNotCalc/(float)nrOfAll;
	}
	
	
	public void saveMatrix(String toFile){
		try {
			ObjectOutputStream oo;

			oo = new ObjectOutputStream(new java.io.BufferedOutputStream(
					new java.io.FileOutputStream(toFile)));

			oo.writeObject(sparseMatrix);
			oo.flush();
			oo.close();

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();			
		}
	}
	
	public void loadMatrix(String fromFile){		
		try {
			ObjectInputStream oo;

			oo = new ObjectInputStream(new BufferedInputStream(
					new FileInputStream(fromFile)));

			sparseMatrix = (SparseRealMatrix) oo.readObject();
			oo.close();			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();			
		}
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println(System.getProperties().toString());
//		float[][] datas= new float[13][2];
//		
//		datas[0]=new float[]{0.1f,0.1f};
//		datas[1]=new float[]{0.1f,0.2f};
//		datas[2]=new float[]{0.2f,0.1f};
//		datas[3]=new float[]{0.2f,0.2f};
//		
//		datas[4]=new float[]{0.8f,0.8f};
//		datas[5]=new float[]{0.8f,0.9f};
//		datas[6]=new float[]{0.9f,0.8f};
//		datas[7]=new float[]{0.9f,0.9f};
//		datas[8]=new float[]{0.85f,0.85f};
//		
//		
//		datas[9]=new float[]{0.1f,0.8f};
//		datas[10]=new float[]{0.1f,0.9f};
//		datas[11]=new float[]{0.2f,0.8f};
//		datas[12]=new float[]{0.2f,0.9f};
//		
//		Distancematrix d= new Distancematrix(datas);
//		System.out.println(d.getDistance(1, 2));
//		d.saveMatrix("distanceTest.matrix");
//		d= new Distancematrix(datas);
//		d.loadMatrix("distanceTest.matrix");
		
	}

}
